﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Media;
using System.Xml.Linq;
using System.Xml.XPath;
using CuteRibs.MVVMLib;
using CuteRibs.WowArmory.Resources;

namespace CuteRibs.WowArmory.ViewModels
{
	public class SearchResultViewModel : ViewModelBase
	{
		private string term;

		public string Term
		{
			get { return this.term; }
			set
			{
				if (this.term != value)
				{
					this.term = value;
					this.NotifyPropertyChanged("Term");
				}
			}
		}

		public string Title { get; set; }
		public List<SearchResultItemViewModel> Items { get; set; }
		public string Field { get; set; }
		public int PageNumber { get; set; }
		public int PageCount { get; set; }

		protected XDocument XDocument { get; set; }

		public SearchResultViewModel(string xhtml, string term)
		{
			this.Term = term;

			if (!string.IsNullOrWhiteSpace(xhtml))
			{
				this.XDocument = XDocument.Parse(xhtml.Replace(" xmlns=\"http://www.w3.org/1999/xhtml\"", string.Empty));
				this.ParsePages();
				this.GenerateItems();
				this.Title = AppRes.Title_Summary;
			}
		}

		private void ParsePages()
		{
			var pagination = this.XDocument.XPathSelectElement("//ul[@class='ui-pagination'][1]");

			if (pagination != null)
			{
				var page = pagination.XPathSelectElement("li[@class='current']/a");
				this.PageNumber = Convert.ToInt32(page.Attribute("data-pagenum").Value);
				this.PageCount = pagination.XPathSelectElements("li/a[@data-pagenum]").Select(e => Convert.ToInt32(e.Attribute("data-pagenum").Value)).Max();
			}
		}

		protected virtual void GenerateItems()
		{
			var result = this.XDocument.XPathSelectElement("//ul[@id='menu-search']");
			this.Items = new List<SearchResultItemViewModel>();
			string href, field = string.Empty;
			int index;

			foreach (var a in result.XPathSelectElements("li/a").Skip(1))
			{
				var item = new SummarySearchResultItemViewModel();
				href = a.Attribute("href").Value;
				index = href.IndexOf("f=") + 2;

				for (var i = index; i < href.Length; i++)
				{
					if (!char.IsLetter(href[i]))
					{
						item.Field = href.Substring(index, i - index);
						break;
					}
				}

				if (item.Field == null)
				{
					item.Field = href.Substring(index);
				}

				item.Title = AppRes.ResourceManager.GetString("Title_" + item.Field);
				item.Count = a.XPathSelectElement("span/span").Value.Trim();
				this.Items.Add(item);
			}
		}

		internal static SolidColorBrush GetClassColor(string classIcon)
		{
			var classNumber = classIcon.Substring(classIcon.LastIndexOf('_') + 1).Replace(".jpg", string.Empty);
			return App.GetClassColor(classNumber);
		}

		internal static SolidColorBrush GetSideColor(string sideIcon)
		{
			var side = sideIcon.Substring(sideIcon.LastIndexOf('_') + 1).Replace(".jpg", string.Empty);
			return App.GetSideColor(side);
		}
	}

	public class CharacterSearchResultViewModel : SearchResultViewModel
	{
		public CharacterSearchResultViewModel(string xhtml, string term, int page)
			: base(xhtml, term)
		{
			this.Title = AppRes.Title_wowcharacter;
			this.Field = SearchField.Character;
		}

		protected override void GenerateItems()
		{
			var tbody = this.XDocument.XPathSelectElement("//div[@class='view-table']//tbody");
			this.Items = new List<SearchResultItemViewModel>();

			foreach (var tr in tbody.Elements())
			{
				var character = new CharacterSearchResultItemViewModel();
				var tds = tr.Elements();

				character.Slug = GetSlug(tds.ElementAt(0).Element("a").Attribute("href").Value);
				character.Icon = tds.ElementAt(0).Descendants("img").First().Attribute("src").Value;
				character.Name = tds.ElementAt(0).Descendants("strong").First().Value.Trim();
				character.Level = tds.ElementAt(1).Value.Trim();
				character.Race = tds.ElementAt(2).Descendants("span").First().Attribute("data-tooltip").Value;
				character.Class = tds.ElementAt(3).Descendants("span").First().Attribute("data-tooltip").Value;
				character.ClassColor = GetClassColor(tds.ElementAt(3).Descendants("img").First().Attribute("src").Value);
				character.Side = tds.ElementAt(4).Descendants("span").First().Attribute("data-tooltip").Value;
				character.SideColor = GetSideColor(tds.ElementAt(4).Descendants("img").First().Attribute("src").Value);
				character.Guild = tds.ElementAt(5).Value.Trim();
				character.Realm = tds.ElementAt(6).Value.Trim();
				this.Items.Add(character);
			}
		}

		private static string GetSlug(string href)
		{
			// /wow/en/character/earthen-ring/Ghost/

			try
			{
				return href.Split('/')[4];
			}
			catch { }

			return string.Empty;
		}
	}

	public class GuildSearchResultViewModel : SearchResultViewModel
	{
		public GuildSearchResultViewModel(string xhtml, string term, int page)
			: base(xhtml, term)
		{
			this.Title = AppRes.Title_wowguild;
			this.Field = SearchField.Guild;
		}

		protected override void GenerateItems()
		{
			var tbody = this.XDocument.XPathSelectElement("//div[@class='view-table']//tbody");
			this.Items = new List<SearchResultItemViewModel>();

			foreach (var tr in tbody.Elements())
			{
				var guild = new GuildSearchResultItemViewModel();
				var tds = tr.Elements();
				guild.Name = tds.ElementAt(0).Descendants("strong").First().Value;
				guild.Realm = tds.ElementAt(1).Value;
				guild.BattleGroup = tds.ElementAt(2).Value;
				guild.Side = tds.ElementAt(3).Descendants("span").First().Attribute("data-tooltip").Value;
				guild.SideColor = GetSideColor(tds.ElementAt(3).Descendants("img").First().Attribute("src").Value);
				guild.Level = tds.ElementAt(4).Value;
				this.Items.Add(guild);
			}
		}
	}

	public class ItemSearchResultViewModel : SearchResultViewModel
	{
		public ItemSearchResultViewModel(string xhtml, string term, int page)
			: base(xhtml, term)
		{
			this.Title = AppRes.Title_wowitem;
			this.Field = SearchField.Item;
		}

		protected override void GenerateItems()
		{
			var tbody = this.XDocument.XPathSelectElement("//div[@class='view-table']//tbody");
			this.Items = new List<SearchResultItemViewModel>();

			foreach (var tr in tbody.Elements())
			{
				var item = new ItemSearchResultItemViewModel();
				var tds = tr.Elements();
				item.Name = tds.ElementAt(0).Descendants("strong").First().Value;

				var a = tds.ElementAt(0).Descendants("a").First();
				var str = a.Attribute("href").Value;
				item.Id = str.Substring(str.LastIndexOf('/') + 1);
				str = a.Attribute("class").Value;
				item.Quality = str.Substring(str.LastIndexOf('q') + 1);
				item.QualityColor = App.GetItemColor(item.Quality);
				str = tds.ElementAt(0).Descendants("span").First().Attribute("style").Value;
				item.Icon = str.Remove(str.LastIndexOf('.')).Substring(str.LastIndexOf('/') + 1);
				item.ItemLevel = tds.ElementAt(1).Value.Trim();
				item.RequiredLevel = tds.ElementAt(2).Value.Trim();
				item.InventoryType = tds.ElementAt(4).FirstNode.ToString().Trim();
				var em = tds.ElementAt(4).Element("em");
				item.EquipmentType = em == null ? string.Empty : em.Value.Trim();
				this.Items.Add(item);
			}
		}
	}

	public class ArenaTeamSearchResultViewModel : SearchResultViewModel
	{
		public ArenaTeamSearchResultViewModel(string xhtml, string term, int page)
			: base(xhtml, term)
		{
			this.Title = AppRes.Title_wowarenateam;
			this.Field = SearchField.ArenaTeam;
		}

		protected override void GenerateItems()
		{
			var tbody = this.XDocument.XPathSelectElement("//div[@class='view-table']//tbody");
			this.Items = new List<SearchResultItemViewModel>();

			foreach (var tr in tbody.Elements())
			{
				var team = new ArenaTeamSearchResultItemViewModel();
				var tds = tr.Elements();
				team.Name = tds.ElementAt(0).Descendants("strong").First().Value;
				team.Side = tds.ElementAt(1).Value;
				team.Realm = tds.ElementAt(2).Value;
				team.BattleGroup = tds.ElementAt(3).Value;
				team.Side = tds.ElementAt(4).Descendants("span").First().Attribute("data-tooltip").Value;
				team.SideColor = GetSideColor(tds.ElementAt(4).Descendants("img").First().Attribute("src").Value);
				team.Rating = tds.ElementAt(5).Value;
				this.Items.Add(team);
			}
		}
	}

	public class ContentSearchResultViewModel : SearchResultViewModel
	{
		public ContentSearchResultViewModel(string xhtml, string term, int page)
			: base(xhtml, term)
		{
			this.Title = AppRes.Title_static;
			this.Field = SearchField.Content;
		}

		protected override void GenerateItems()
		{
			var list = this.XDocument.XPathSelectElement("//div[@class='view-list']");
			this.Items = new List<SearchResultItemViewModel>();

			foreach (var item in list.Elements())
			{
				var content = new ContentSearchResultItemViewModel();
				XElement el;

				if ((el = item.XPathSelectElement("a[@class='thumbnail']/span/img")) != null)
				{
					content.Icon = el.Attribute("src").Value;
				}

				if ((el = item.XPathSelectElement("h4/a")) != null)
				{
					content.Link = el.Attribute("href").Value;
					content.Title = el.Value.Trim();
				}

				if ((el = item.XPathSelectElement("div[@class='meta']")) != null)
				{
					content.Category = el.FirstNode.ToString().Trim();
					content.Tags = el.Elements().Select(e => e.Value).Aggregate((n, i) => i + ", " + n);
				}

				if ((el = item.XPathSelectElement("div[@class='content']")) != null)
				{
					content.Description = el.Value.Trim();
				}

				this.Items.Add(content);
			}
		}
	}

	public class ForumSearchResultViewModel : SearchResultViewModel
	{
		public ForumSearchResultViewModel(string xhtml, string term, int page)
			: base(xhtml, term)
		{
			this.Title = AppRes.Title_post;
			this.Field = SearchField.Forum;
		}

		protected override void GenerateItems()
		{
			var list = this.XDocument.XPathSelectElement("//div[@class='view-list']");
			this.Items = new List<SearchResultItemViewModel>();

			foreach (var item in list.Elements())
			{
				var forum = new ForumSearchResultItemViewModel();
				XElement el;

				if ((el = item.XPathSelectElement("h4/span[contains(@class,'status')]")) != null)
				{
					forum.IsReply = true;
				}

				if ((el = item.XPathSelectElement("h4/a")) != null)
				{
					forum.PostLink = el.Attribute("href").Value;
					forum.Title = el.Value.Trim();
					forum.Replies = el.NextNode.ToString().Trim();
				}

				if ((el = item.XPathSelectElement("div[@class='meta']/a[@class='sublink']")) != null)
				{
					forum.ForumLink = el.Attribute("href").Value;
					forum.Forum = el.Value.Trim();
				}

				if ((el = item.XPathSelectElement("div[@class='meta']/a[@class='author']")) != null)
				{
					forum.Author = el.Value.Trim();
					forum.DateTime = el.NextNode.ToString().Trim();
				}

				if ((el = item.XPathSelectElement("div[@class='content']")) != null)
				{
					forum.Brief = el.Value.Trim();
				}

				this.Items.Add(forum);
			}
		}
	}

	public class BlogSearchResultViewModel : SearchResultViewModel
	{
		public BlogSearchResultViewModel(string xhtml, string term, int page)
			: base(xhtml, term)
		{
			this.Title = AppRes.Title_article;
			this.Field = SearchField.Blog;
		}

		protected override void GenerateItems()
		{
			var list = this.XDocument.XPathSelectElement("//div[@class='view-list']");
			this.Items = new List<SearchResultItemViewModel>();

			foreach (var item in list.Elements())
			{
				var blog = new BlogSearchResultItemViewModel();
				XElement el;

				if ((el = item.XPathSelectElement("a[@class='thumbnail']/span/img")) != null)
				{
					blog.Icon = el.Attribute("src").Value;
				}

				if ((el = item.XPathSelectElement("h4/a")) != null)
				{
					blog.Link = el.Attribute("href").Value;
					blog.Title = el.Value.Trim();
					blog.Comments = el.NextNode.ToString().Trim();
				}

				if ((el = item.XPathSelectElement("div[@class='meta']/a")) != null)
				{
					blog.Author = el.Value.ToString().Trim();
					blog.DateTime = el.NextNode.ToString().Trim();
				}

				if ((el = item.XPathSelectElement("div[@class='content']")) != null)
				{
					blog.Brief = el.Value.Trim();
				}

				this.Items.Add(blog);
			}
		}
	}

	public class SupportSearchResultViewModel : SearchResultViewModel
	{
		public SupportSearchResultViewModel(string xhtml, string term, int page)
			: base(xhtml, term)
		{
			this.Title = AppRes.Title_support;
			this.Field = SearchField.Support;
		}

		protected override void GenerateItems()
		{
			var list = this.XDocument.XPathSelectElement("//div[@class='view-list']");
			this.Items = new List<SearchResultItemViewModel>();

			foreach (var item in list.Elements())
			{
				var support = new SupportSearchResultItemViewModel();
				XElement el;

				if ((el = item.XPathSelectElement("h4/a")) != null)
				{
					support.Link = el.Attribute("href").Value;
					support.Title = el.Value.Trim();
				}

				if ((el = item.XPathSelectElement("div[@class='content']")) != null)
				{
					support.Brief = el.Value.Trim();
				}

				if ((el = item.XPathSelectElement("div[@class='meta'][1]")) != null)
				{
					support.DateTime = el.Value.Trim();
				}

				if ((el = item.XPathSelectElement("div[@class='meta'][2]")) != null)
				{
					support.Keywords = el.Elements("a").Select(e => e.Value).Aggregate((n, i) => i + ", " + n);
				}

				this.Items.Add(support);
			}
		}
	}
}
